import * as cc from "cc";
import yyComponent from "../../Script/Common/yyComponent";
import Action3dManager, { ActionMngType } from "../../Script/Common/Action3dManager";
import { EventType } from "../../Script/GameSpecial/GameEventType";
import { GlobalEnum } from "../../Script/GameSpecial/GlobalEnum";
import GameConfig from "../../Script/GameSpecial/GameConfig";

const { ccclass, property } = cc._decorator;
/**关卡中使用的相机 */
@ccclass
export default class LevelCamera extends yyComponent {

    public init() {
        this.anchorNode = this.node;
        this.camera = this.node.getComponentInChildren(cc.Camera);
        this.cameraNode = this.camera.node;

        this.initCameraDis();
        this.initFollowState();
        this.initScaleData();
        this.initOriginalTransform();
        this.initCustomUpdateState();

        this.registAllCustomUpdate();
        this.onEvents();
    }

    protected registAllCustomUpdate() {
        this.registCustomUpdate(GlobalEnum.LevelCameraState.follow, this.stepSlowFollow);
    }
    protected onEvents() {
        this.on(EventType.LevelEvent.shakeScreen, this.shake, this);
        this.on(EventType.LevelEvent.scaleScreen, this.scaleScreen, this);
        this.on(EventType.LevelEvent.updateRoleScale, this.onUpdateRoleScale, this);
    }

    public reset() {
        this.followTarget = null;
        this.stopScaleScreen();
        this.resetScaleData();
        this.stopShake();
        this.resumeOriginalTransform();
    }

    /*****************************************对外功能*****************************************/
    /**进入关卡 */
    public enterLevel() {
        this.enterCustomUpdateState(GlobalEnum.LevelCameraState.follow);
    }
    //#region 相机组件
    /**相机组件 */
    @property(cc.Camera)
    public camera: cc.Camera = null;
    /**相机组件所在节点 */
    @property(cc.Node)
    protected cameraNode: cc.Node = null;
    /**相机朝向的节点 */
    @property(cc.Node)
    protected anchorNode: cc.Node = null;
    protected _originalPos: cc.Vec3;
    protected __originalPos: cc.Vec3;
    protected _originalEulerAngles: cc.Vec3;
    protected initOriginalTransform() {
        this._originalPos = cc.v3();
        this.cameraNode.getPosition(this._originalPos);
        this.__originalPos = cc.v3();
        this.__originalPos.set(this._originalPos);
        this._originalEulerAngles = cc.v3();
        this._originalEulerAngles.set(this.cameraNode.eulerAngles);
    }
    //#endregion

    //#region 视野切换
    /**恢复到原始视角 */
    public resumeOriginalTransform(duration: number = 0, cb?: Function) {
        this._originalPos.set(this.__originalPos);
        if (!duration) {
            this.cameraNode.setPosition(this._originalPos);
            this.cameraNode.eulerAngles = this._originalEulerAngles;
            return;
        }
        this.changeCamera({
            duration: duration,
            pos: this._originalPos,
            angle: this._originalEulerAngles,
            cb: cb
        });
    }
    /**视角切换，将相机节点切换到相对相机根节点的指定的位置与角度 */
    public changeCamera(data: { duration?: number, pos?: cc.Vec3, angle?: cc.Vec3, cb?: Function }) {
        if (!data.duration) {
            if (!!data.pos) this.cameraNode.setPosition(data.pos);
            if (!!data.angle) this.cameraNode.eulerAngles = data.angle;
            if (!!data.cb) data.cb();
            return;
        }
        let move = null;
        let rotate = null;
        if (!!data.pos) {
            move = Action3dManager.moveTo(data.duration, data.pos);
        }
        if (!!data.angle) {
            rotate = Action3dManager.rotateTo(data.duration, data.angle);
        }
        let spawn = null;
        if (!!move && !!rotate) {
            spawn = Action3dManager.spawn(move, rotate);
        } else if (!!move) {
            spawn = Action3dManager.spawn(move);
        } else if (!!rotate) {
            spawn = Action3dManager.spawn(rotate);
        }
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        if (!!spawn && !!data.cb) {
            let callFun = Action3dManager.callFun(data.cb);
            let sequence = Action3dManager.sequence(spawn, callFun);
            actMng.runAction(this.cameraNode, sequence);
        } else if (!!spawn) {
            actMng.runAction(this.cameraNode, spawn);
        } else if (!!data.cb) {
            data.cb();
        }
    }
    /**移动到指定位置，移动相机根节点 */
    public moveTo(duration: number, pos: cc.Vec3, cb?: Function) {
        if (duration == 0) {
            this.node.setPosition(pos);
            if (!!cb) {
                cb();
            }
            return;
        }
        let actMng = Action3dManager.getMng(ActionMngType.Level);
        let action = Action3dManager.moveTo(duration, pos);
        action.easing(Action3dManager.easeOut(3));
        if (!!cb) {
            let callFun = Action3dManager.callFun(cb);
            actMng.runAction(this.node, Action3dManager.sequence(action, callFun));
        } else {
            actMng.runAction(this.node, action);
        }
    }
    //#endregion

    //#region 震屏功能
    protected shakeElapsed: number = 0;
    protected shakeDuration: number = 0.3;
    protected shakeRadius: number = 0.1;
    protected shaking: boolean = false;
    /**震屏 */
    public shake(data: any = {}) {
        this.shakeElapsed = 0;
        this.shakeDuration = data.duration || 0.3;
        this.shakeRadius = data.radius || 0.1;
        if (this.shaking) return;
        this.stopScaleScreen();
        let thread = Action3dManager.thread(this.randomCameraPos, this);
        Action3dManager.getMng(ActionMngType.Level).runAction(this, thread);
        this.shaking = true;
    }
    protected randomCameraPos(dt: number) {
        this.shakeElapsed += dt;
        if (this.shakeElapsed >= this.shakeDuration) {
            this.stopShake();
        } else {
            let scope = this.shakeRadius * (1 - this.shakeElapsed / this.shakeDuration);
            let r = Math.random() * 6.28;
            let x = Math.sin(r) * scope;
            let y = Math.cos(r) * scope;
            this.cameraNode.setPosition(this._originalPos.x + x, this._originalPos.y + y, this._originalPos.z);
        }
    }
    public stopShake() {
        this.shakeElapsed = 0;
        this.shaking = false;
        this.cameraNode.setPosition(this._originalPos);
        Action3dManager.getMng(ActionMngType.Level).stopAllActions(this);
    }
    //#endregion

    //#region 后座力
    public shock(data: { duration: number, offset: cc.Vec3 }) {
        this.stopShake();
        let p = this._originalPos;
        this.cameraNode.setPosition(p.x + data.offset.x, p.y + data.offset.y, p.z + data.offset.z);
        let move = Action3dManager.moveTo(data.duration, p);
        Action3dManager.getMng(ActionMngType.Level).runAction(this.cameraNode, move);
    }
    public stopShock() {
        Action3dManager.getMng(ActionMngType.Level).stopAllActions(this.cameraNode);
    }
    //#endregion

    //#region 爆炸效果：视野放大
    protected normalScale: number;
    protected maxScale: number;
    protected scaleElapsed: number;
    protected scaleDuration: number;
    protected scaleCenter: cc.Vec2;
    protected scaleStay: number;
    protected scaleBackDuration: number;

    protected initScaleData() {
        this.normalScale = 1;
        this.maxScale = 1.5;
        this.scaleElapsed = 0;
        this.scaleDuration = 0.1;
        this.scaleStay = 0.1;
        this.scaleCenter = cc.v2();
        this.scaleBackDuration = 0;
    }
    protected resetScaleData() {
        this.scaleElapsed = 0;
    }
    protected scaleScreen(data) {
        this.stopShake();
        this.maxScale = data.maxScale || 1.5;
        if (!!data.center) {
            this.scaleCenter.x = data.center.x - this.node.position.x;
            this.scaleCenter.y = data.center.y - this.node.position.y;
        } else {
            this.scaleCenter.x = 0;
            this.scaleCenter.y = 0;
        }
        this.scaleDuration = data.duration || 0.1;
        this.scaleStay = data.stay || 0.1;
        this.scaleElapsed = 0;
        this.scaleBackDuration = data.scaleBackDuration || 0;

        let thread = Action3dManager.thread(this.threadScaleScreen, this);
        Action3dManager.getMng(ActionMngType.Level).runAction(this, thread);
    }
    protected threadScaleScreen(dt: number) {
        this.scaleElapsed += dt;
        if (this.scaleElapsed > this.scaleDuration + this.scaleStay + this.scaleBackDuration) {
            this.stopScaleScreen();
            return;
        }
        if (this.scaleElapsed <= this.scaleDuration) {
            let r = this.scaleElapsed / this.scaleDuration;
            let s = this.normalScale + (this.maxScale - this.normalScale) * r;
            let x = this.scaleCenter.x - this.scaleCenter.x / s;
            let y = this.scaleCenter.y - this.scaleCenter.y / s;
            this.cameraNode.setPosition(x, y);
            // this.camera.zoomRatio = s;
        } else if (this.scaleElapsed > this.scaleDuration + this.scaleStay) {
            let t = this.scaleElapsed - this.scaleDuration - this.scaleStay;
            let r = t / this.scaleBackDuration;
            let s = this.maxScale - (this.maxScale - this.normalScale) * r;
            let x = this.scaleCenter.x - this.scaleCenter.x / s;
            let y = this.scaleCenter.y - this.scaleCenter.y / s;
            this.cameraNode.setPosition(x, y);
            // this.camera.zoomRatio = s;
        }
    }
    protected stopScaleScreen() {
        this.cameraNode.setPosition(this._originalPos);
        // this.camera.zoomRatio = 1;
        Action3dManager.getMng(ActionMngType.Level).stopAllActions(this);
    }

    //#endregion

    //#region 视野跟随
    /**跟随的目标节点 */
    protected followTarget: cc.Node;
    protected cachePos: cc.Vec3;
    /**相机坐标范围 */
    protected viewScope: { xMin: number, xMax: number, yMin: number, yMax: number };
    /**相机与跟随目标的偏移范围，距离超出该值时缓动跟随 */
    protected offsetScope: { xMin: number, xMax: number, yMin: number, yMax: number };
    protected initFollowState() {
        this.followTarget = null;
        this.cachePos = cc.v3();
        this.viewScope = {
            xMin: -100,
            xMax: 100,
            yMin: -100,
            yMax: 100,
        };
        this.offsetScope = {
            xMin: -100,
            xMax: 100,
            yMin: 0,
            yMax: 100,
        };
    }
    public setViewScope(xMin, xMax, yMin, yMax) {
        this.viewScope.xMin = xMin;
        this.viewScope.xMax = xMax;
        this.viewScope.yMin = yMin;
        this.viewScope.yMax = yMax;
    }
    public setOffsetScope(xMin, xMax, yMin, yMax) {
        this.offsetScope.xMin = xMin;
        this.offsetScope.xMax = xMax;
        this.offsetScope.yMin = yMin;
        this.offsetScope.yMax = yMax;
    }
    public setTarget(followTarget: cc.Node) {
        this.followTarget = followTarget;
        this.anchorNode.getPosition(this.cachePos);
    }
    protected stepSlowFollow(dt: number) {
        if (!this.followTarget) return;
        //无缓动跟随：
        // this.anchorNode.setPosition(this.followTarget.x, this.followTarget.y, this.followTarget.z);
        this.anchorNode.setPosition(this.followTarget.position.x, 0, this.followTarget.position.z);
        return;

        let x = this.followTarget.position.x - this.cachePos.x;
        if (x < this.offsetScope.xMin) {
            this.cachePos.x = this.followTarget.position.x - this.offsetScope.xMin;
        } else if (x > this.offsetScope.xMax) {
            this.cachePos.x = this.followTarget.position.x - this.offsetScope.xMax;
        }
        // if (x < this.offsetScope.xMin || x > this.offsetScope.xMax) {
        //     x *= 0.1;
        //     this.cachePos.x += x;
        // }
        let y = this.followTarget.position.y - this.cachePos.y;
        if (y < this.offsetScope.yMin) {
            this.cachePos.y = this.followTarget.position.y - this.offsetScope.yMin;
        } else if (y > this.offsetScope.yMax) {
            this.cachePos.y = this.followTarget.position.y - this.offsetScope.yMax;
        }
        // if (y < this.offsetScope.yMin || y > this.offsetScope.yMax) {
        //     y *= 0.1;
        //     this.cachePos.y += y;
        // }

        this.clampView();
        this.anchorNode.setPosition(this.cachePos);
    }
    protected clampView() {
        if (this.cachePos.x < this.viewScope.xMin) {
            this.cachePos.x = this.viewScope.xMin;
        } else if (this.cachePos.x > this.viewScope.xMax) {
            this.cachePos.x = this.viewScope.xMax;
        }

        if (this.cachePos.y < this.viewScope.yMin) {
            this.cachePos.y = this.viewScope.yMin;
        } else if (this.cachePos.y > this.viewScope.yMax) {
            this.cachePos.y = this.viewScope.yMax;
        }
    }
    //#endregion

    //#region 视野范围
    /**相机到锚点的距离 */
    protected cameraDis: number = 0;
    protected initCameraDis() {
        let p = this.cameraNode.position;
        this.cameraDis = p.length();
    }
    protected onUpdateRoleScale(scale: number) {
        let r = (this.cameraDis + 25 * (scale - GameConfig.GameRule.minScale)) / this.cameraDis;
        this._originalPos.x = this.__originalPos.x * r;
        this._originalPos.y = this.__originalPos.y * r;
        this._originalPos.z = this.__originalPos.z * r;
        let move = Action3dManager.moveTo(2, this._originalPos);
        Action3dManager.getMng(ActionMngType.Level).runAction(this.cameraNode, move);
    }
    //#endregion

}
